package com.wei.czz.framework.common.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.po.UserPo;
import com.wei.czz.common.tool.PageDto;
import com.wei.czz.common.tool.PageQuery;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.vo.common.limitConfig.LimitConfigFormVo;
import com.wei.czz.framework.common.dao.LimitConfigDao;
import com.wei.czz.framework.common.entity.LimitConfigEntity;
import com.wei.czz.framework.common.service.LimitConfigService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.*;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;


/**
 * Created by IntelliJ IDEA.
 *
 * @author wei
 * date: 2023-02-16 21:38:02
 * className: LimitConfigServiceImpl 限流请求服务接口实现类
 * version: 1.0
 * description:
 */
@Service("limitConfigService")
@AllArgsConstructor
public class LimitConfigServiceImpl extends ServiceImpl<LimitConfigDao, LimitConfigEntity>
        implements LimitConfigService {

    private static final Logger log = LoggerFactory.getLogger(LimitConfigServiceImpl.class);

    @Override
    public void saveOrEdit(LimitConfigEntity limitConfig) {
        Long id = limitConfig.getId();
        if (Objects.isNull(id)) {

            int count = baseMapper.insert(limitConfig);
            log.info("插入限流配置完成。count={}", count);
        } else {

            int count = baseMapper.updateById(limitConfig);
            log.info("修改限流配置完成。count={}", count);
        }
    }

    @Override
    public PageDto<LimitConfigEntity> getPageList(LimitConfigFormVo limitConfigFormVo) {
        // 构造mp分页对象
        Page<LimitConfigEntity> page = PageQuery.initPage(limitConfigFormVo);

        LambdaQueryWrapper<LimitConfigEntity> limitConfigLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 匹配 接口路径、状态、删除状态 字段
        limitConfigLambdaQueryWrapper.like(StringUtils.isNotBlank(limitConfigFormVo.getWord()),
                        LimitConfigEntity::getRequestKey, limitConfigFormVo.getWord())
                .eq(Objects.nonNull(limitConfigFormVo.getType()), LimitConfigEntity::getType,
                        limitConfigFormVo.getType())
                .eq(Objects.nonNull(limitConfigFormVo.getStatus()), LimitConfigEntity::getStatus,
                        limitConfigFormVo.getStatus())
                .eq(LimitConfigEntity::getDeleteStatus, CommonEnum.ZERO.getValue());

        // 查询数据库系统字典表，分页获取数据
        baseMapper.selectPage(page, limitConfigLambdaQueryWrapper);
        log.info("分页查询限流配置完成。list.size={} totalNum={}", page.getRecords().size(), page.getTotal());

        return new PageDto<>(page);
    }

    @Override
    public List<LimitConfigEntity> queryUsableLimitConfigList() {

        LambdaQueryWrapper<LimitConfigEntity> limitConfigLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 查询 接口路径、限流类型、时间数值、时间单位、滑动窗口数量、最大次数、限流时长、限流回复消息 字段
        limitConfigLambdaQueryWrapper.select(LimitConfigEntity::getRequestKey, LimitConfigEntity::getType, LimitConfigEntity::getTimeNum,
                LimitConfigEntity::getTimeType, LimitConfigEntity::getWindowNum, LimitConfigEntity::getMaxNum, LimitConfigEntity::getLimitTime,
                LimitConfigEntity::getMessage, LimitConfigEntity::getVersion);
        // 匹配 状态、删除状态 字段
        limitConfigLambdaQueryWrapper.eq(LimitConfigEntity::getStatus, CommonEnum.ZERO.getValue())
                .eq(LimitConfigEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询数据
        return baseMapper.selectList(limitConfigLambdaQueryWrapper);
    }

    @Override
    public LimitConfigEntity get(Long id) {
        LimitConfigEntity limitConfig = baseMapper.selectById(id);
        if (Objects.isNull(limitConfig)) {
            log.info("限流配置不存在");
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "限流配置不存在，请确认");
        }
        if (CommonEnum.ONE.getValue().equals(limitConfig.getDeleteStatus())) {
            log.info("限流配置已删除");
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "限流配置不存在，请确认");
        }
        return limitConfig;
    }

    @Override
    public List<LimitConfigEntity> getList(List<Long> idList) {
        if (CollectionUtils.isEmpty(idList)) {
            log.info("批量获取限流配置，传入主键列表为空");
            return Collections.emptyList();
        }
        LambdaQueryWrapper<LimitConfigEntity> limitConfigLambdaQueryWrapper = new LambdaQueryWrapper<>();
        limitConfigLambdaQueryWrapper.in(LimitConfigEntity::getId, idList)
                .eq(LimitConfigEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询
        List<LimitConfigEntity> limitConfigList = baseMapper.selectList(limitConfigLambdaQueryWrapper);
        log.info("查询限流配置完成。size={}", limitConfigList.size());
        return limitConfigList;
    }

    @Override
    public List<LimitConfigEntity> findList(List<String> requestKeyList, Integer type) {
        if (CollectionUtils.isEmpty(requestKeyList) && Objects.isNull(type)) {
            log.info("获取限流配置，传入‘接口路径列表’和‘限流类型’参数为空");
            return Collections.emptyList();
        }
        LambdaQueryWrapper<LimitConfigEntity> limitConfigLambdaQueryWrapper = new LambdaQueryWrapper<>();
        limitConfigLambdaQueryWrapper.in(!CollectionUtils.isEmpty(requestKeyList), LimitConfigEntity::getRequestKey,
                        requestKeyList)
                .eq(Objects.nonNull(type), LimitConfigEntity::getType, type)
                .eq(LimitConfigEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 查询
        List<LimitConfigEntity> limitConfigList = baseMapper.selectList(limitConfigLambdaQueryWrapper);
        log.info("查询限流配置完成。param.size={} list.size={}", requestKeyList.size(), limitConfigList.size());
        return limitConfigList;
    }

    @Override
    public int optimisticUpdate(LimitConfigEntity limitConfig) {
        // 修改限流配置
        int count = baseMapper.optimisticUpdate(limitConfig);
        log.info("乐观更新限流配置完成。count={}", count);
        return count;
    }

    @Transactional
    @Override
    public List<LimitConfigEntity> optimisticBatchUpdate(List<LimitConfigEntity> limitConfigList) {
        if (CollectionUtils.isEmpty(limitConfigList)) {
            log.info("批量修改限流配置，传入限流配置对象列表参数为空");
            return Collections.emptyList();
        }
        List<LimitConfigEntity> successLimitConfigList = new ArrayList<>();
        // 执行批量修改
        boolean bool = this.executeBatch(limitConfigList, ((sqlSession, limitConfig) -> {
            // 获取dao对象
            LimitConfigDao limitConfigDao = sqlSession.getMapper(LimitConfigDao.class);
            // 修改数据
            int count = limitConfigDao.optimisticUpdate(limitConfig);
            if (count != 0) {
                successLimitConfigList.add(limitConfig);
            }
        }));
        log.info("批量修改限流配置完成。success.size={} bool={}", successLimitConfigList.size(), bool);
        return successLimitConfigList;
    }

    @Override
    public void delete(List<Long> idList) {
        // 获取操作用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        LambdaUpdateWrapper<LimitConfigEntity> limitConfigLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        limitConfigLambdaUpdateWrapper.set(LimitConfigEntity::getDeleteStatus, CommonEnum.ONE.getValue())
                .set(LimitConfigEntity::getUpdateTime, date)
                .set(LimitConfigEntity::getUpdateUser, userPo.getUsername())
                .set(LimitConfigEntity::getUpdateUserId, userPo.getUserId());
        limitConfigLambdaUpdateWrapper.in(LimitConfigEntity::getId, idList)
                .eq(LimitConfigEntity::getDeleteStatus, CommonEnum.ZERO.getValue());
        // 删除
        int count = baseMapper.update(limitConfigLambdaUpdateWrapper);
        log.info("删除限流配置完成。count={}", count);
    }

}